using System;
using System.Runtime.InteropServices;
using System.Text;

using Pegasus.Runtime.InteropServices;
using Pegasus.Windows.API;
using Pegasus.Windows.API.Enumerations;
using Pegasus.Windows.API.Interfaces;
using Pegasus.Windows.API.Structures;

namespace Pegasus.Windows.Shell
{
	/// <summary>
	///  This is a folder in the shell namespace.
	/// </summary>
	public class FolderItem : ShellItem
	{
		// Local Instance Values
		private IShellFolder m_shellFolder = null;
		private ShellItemCollection m_itemsCollection = null;

		/// <summary>
		/// Initializes a new instance of the <see cref="DesktopItem"/> class.
		/// </summary>
		/// <param name="pidl">The pidl for the folder item.</param>
		/// <param name="shellFolder">The shell folder.</param>
		public FolderItem( Pidl pidl, IShellFolder shellFolder ) 
			: base( pidl )
		{
			m_shellFolder = shellFolder;
		}

		/// <summary>
		/// Gets the items.
		/// </summary>
		/// <value>The items.</value>
		public ShellItemCollection Items
		{
			get
			{
				if( m_itemsCollection == null )
				{
					m_itemsCollection = BuildItemsCollection();
				}

				return m_itemsCollection;
			}
		}

		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		/// </summary>
		public override void Dispose()
		{
			base.Dispose();

			if( m_shellFolder != null )
			{
				Marshal.ReleaseComObject( m_shellFolder );
				m_shellFolder = null;
			}
		}

		/// <summary>
		/// Builds the items collection.
		/// </summary>
		/// <returns></returns>
		protected virtual ShellItemCollection BuildItemsCollection()
		{
			ShellItemCollection collection = new ShellItemCollection();

			IntPtr ipEnumList = m_shellFolder.EnumObjects( IntPtr.Zero, SHCONTF.FOLDERS | SHCONTF.NONFOLDERS | SHCONTF.INCLUDEHIDDEN );
			IEnumIDList enumList = (IEnumIDList) Marshal.GetTypedObjectForIUnknown( ipEnumList, typeof( IEnumIDList ) );
			if( enumList != null )
			{
				IntPtr ipPidl = IntPtr.Zero;

				while( enumList.Next( 1, out ipPidl ) > 0 )
				{
					ShellItem item = CreateShellItemFromPidl( new Pidl( ipPidl ) );
					if( item != null )
					{
						collection.Add( item );
					}
				}
			}

			return collection;
		}

		/// <summary>
		/// Creates the shell item from pidl.
		/// </summary>
		/// <param name="pidl">The pidl.</param>
		/// <returns></returns>
		protected virtual ShellItem CreateShellItemFromPidl( Pidl pidl )
		{
			SFGAO attributes = SFGAO.FOLDER;
			uint hResult = m_shellFolder.GetAttributesOf( 1, new IntPtr[] { pidl }, ref attributes );


			if( ( attributes & SFGAO.FOLDER ) > 0 )
			{
				IntPtr ipShellFolder = m_shellFolder.BindToObject( pidl, IntPtr.Zero, IID.IShellFolder );
				IShellFolder shellFolder = (IShellFolder) Marshal.GetTypedObjectForIUnknown( ipShellFolder, typeof( IShellFolder ) );

				return new FolderItem( pidl, shellFolder );
			}

			return new FileItem( pidl );
		}
	}
}
